from email.policy import default
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from collections import defaultdict

class SbSaleLinkMo(models.Model):
    _name = 'sb.sale.link.mo'
    _description = 'Delink/Line Work Orders'

    def _default_name(self):
        return self.env['ir.sequence'].next_by_code('sb.sale.link.mo')

    name = fields.Char(string='Ref', default=_default_name)
    sale_order_id = fields.Many2one('sale.order', string='Sale Order')
    partner_id = fields.Many2one('res.partner', string='Customer')
    product_id = fields.Many2one('product.product', 'Customer Part')
    product_tmpl_id = fields.Many2one('product.template')
    delink_mo = fields.Boolean(default=False, string='Delink Mrp')
    link_mo = fields.Boolean(default=False, string='Link Mrp')
    line_ids = fields.One2many('sb.sale.link.mo.line', 'link_mo_id')
    state = fields.Selection([('draft', 'Draft'),
                              ('load_mo', 'Search Mo'),
                              ('link', 'Link'),
                              ('delink', 'Delink'),
                              ('cancel', 'Cancel')],
                             default='draft',
                             string='Status')
    link_or_delink = fields.Selection(related='sale_order_id.link_or_delink')
    sale_order_ids = fields.Many2many('sale.order')

    @api.onchange('sale_order_id')
    def onchange_sale_order_id(self):
        if self.sale_order_id:
            self.partner_id = self.sale_order_id.partner_id.id
            self.product_id = self.sale_order_id.order_line[0].product_id.id
            self.product_tmpl_id = self.sale_order_id.product_tmpl_id.id
        else:
            self.partner_id = None
            self.product_id = None
            self.product_tmpl_id = None

    @api.onchange('link_mo')
    def onchange_delink_mo(self):
        if self.link_mo:
            self.delink_mo = False
        else:
            self.delink_mo = True
        self.line_ids = None

    @api.onchange('delink_mo')
    def onchange_link_mo(self):
        if self.delink_mo:
            self.link_mo = False
        else:
            self.link_mo = True
        self.line_ids = None

    def get_mo_action(self):
        if not self.sale_order_id:
            raise ValidationError('请先选择销售订单！')
        vals = {'line_ids': []}
        if self.delink_mo:
            # 断开工单, 获取已经和so连接的MO
            for line in self.sale_order_id.order_line:
                if line.product_id.detailed_type == 'product':
                    for mrp in line.s_mrp_production_ids:
                        vals['line_ids'].append((0, 0, {'mrp_production_id': mrp.id, 'sale_order_line_id': line.id}))
        else:
            # 连接工单,查找 没有和so连接的mo
            product_ids = []
            for line in self.sale_order_id.order_line:
                if line.product_id.detailed_type == 'product':
                    product_ids.append(line.product_id.id)
            mrp_production_ids = self.sudo().env['mrp.production'].search(
                [('customer', '=', self.partner_id.id),
                 ('product_id', 'in', product_ids),
                 ('state', 'not in', ['to_close', 'cancel', 'done'])])
            if not mrp_production_ids:
                pass
            else:
                sql = "SELECT mrp_production_id FROM mrp_production_sale_order_line_rel"
                self.env.cr.execute(sql)
                s_mrp_production_ids = self.env.cr.dictfetchall()
                s_mrp_production_ids = [mrp['mrp_production_id'] for mrp in s_mrp_production_ids]
                self.env.cr.commit()
                mrp_production_ids = set(mrp_production_ids.ids)
                s_mrp_production_ids = set(s_mrp_production_ids)
                line_ids = [(0, 0, {'mrp_production_id': l}) for l in
                            list(mrp_production_ids.difference(s_mrp_production_ids))]
                vals['line_ids'] = line_ids
        self.write(vals)

    def button_cancel(self):
        self.state = 'cancel'

    def button_confirm(self):
        self.state = 'load_mo'

    def confirm_link(self):
        sol_mrps = defaultdict(list)
        for line in self.line_ids:
            if sol_mrps.get(line.sale_order_line_id):
                sol_mrps[line.sale_order_line_id].append((4, line.mrp_production_id.id))
            else:
                sol_mrps[line.sale_order_line_id] = [(4, line.mrp_production_id.id)]
        for sol, mrps in sol_mrps.items():
            sol.s_mrp_production_ids = mrps
        self.state = 'link'
        self.sale_order_id.link_or_delink = 'link'

        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'type': 'success',
                'title': _("Sale Order Link"),
                'message': _("The ticket is connected！"),
                'next': {
                    'type': 'ir.actions.act_window_close'
                },
            }
        }
    # def confirm_link(self):
    #     if not self.line_ids.filtered(lambda x: x.is_option):
    #         raise ValidationError('请选择要连接的工单')
    #     # 确认连接
    #     order_line = {}
    #     for s_line in self.sale_order_id.order_line:
    #         order_line[s_line.product_id.id] = s_line
    #
    #     mrp_line = {}
    #     for l in self.line_ids:
    #         mrp_product_id = l.mrp_production_id.product_id.id
    #         if l.is_option and not mrp_line.get(mrp_product_id, None):
    #             mrp_line[mrp_product_id] = [(4, l.mrp_production_id.id)]
    #         elif l.is_option and mrp_line.get(mrp_product_id, None):
    #             mrp_line[mrp_product_id].append((4, l.mrp_production_id.id))
    #         else:
    #             pass
    #
    #     for product_id, s_line in order_line.items():
    #         if mrp_line.get(product_id, None):
    #             s_line.s_mrp_production_ids = mrp_line[product_id]
    #     # self.sale_order_id.order_line.s_mrp_production_ids = link_mrp
    #     self.state = 'link'
    #     self.sale_order_id.link_or_delink = 'link'
    #     # self.sale_order_id._compute_status()

    def confirm_delink(self):
        # 断开连接
        delink_mrp = {}
        option_vals = []
        for l in self.line_ids:
            if l.is_option and l.sale_order_line_id in delink_mrp.keys():
                delink_mrp[l.sale_order_line_id].append((3, l.mrp_production_id.id))
                option_vals.append((4, l.mrp_production_id.id))
            elif l.is_option and l.sale_order_line_id not in delink_mrp.keys():
                delink_mrp[l.sale_order_line_id] = [(3, l.mrp_production_id.id)]
                option_vals.append((4, l.mrp_production_id.id))
            else:
                pass
        if not delink_mrp:
            raise ValidationError('请选择要断开的工单')
        for order_line, mrp_val in delink_mrp.items():
            order_line.s_mrp_production_ids = mrp_val
        self.state = 'delink'
        self.sale_order_id.link_or_delink = 'delink'
        self.sale_order_id.option_mrp_production_ids = option_vals
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'type': 'success',
                'title': _("Sale Order Link"),
                'message': _("The work order is successfully disconnected！"),
                'next': {
                    'type': 'ir.actions.act_window_close'
                },
            }
        }



class SbSaleLinkMoLine(models.Model):
    _name = 'sb.sale.link.mo.line'

    link_mo_id = fields.Many2one('sb.sale.link.mo')
    is_option = fields.Boolean(string='Choice', default=True)
    mrp_production_id = fields.Many2one('mrp.production', string='Mrp Order')
    state = fields.Selection(related='mrp_production_id.state', string='Status')
    date_start = fields.Datetime(related='mrp_production_id.date_start')
    date_finished = fields.Datetime(related='mrp_production_id.date_finished', string='Finish Date')
    product_qty = fields.Float(related='mrp_production_id.product_qty')
    sale_order_line_id = fields.Many2one('sale.order.line', string='Order Line')
